package cn.myspringboot.article.service.impl;

import cn.myspringboot.anno.Logs;
import cn.myspringboot.article.mapper.ArticleMapper;
import cn.myspringboot.article.service.ArticleService;
import cn.myspringboot.common.controller.MinIoController;
import cn.myspringboot.user.domain.Article;
import cn.myspringboot.user.domain.Bar;
import cn.myspringboot.user.domain.TypeNameCount;
import cn.myspringboot.user.domain.YearAndMonth;
import cn.myspringboot.user.query.ArticleQuery;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.myspringboot.config.RedisConstant.ARTICLE_READ;
import static cn.myspringboot.config.RedisConstant.ARTICLE_STAR;

@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private MinIoController minIoController;

    @Logs
    @Override
    @Transactional
    public void addArticle(Article article) {
        articleMapper.addArticle(article);
    }

    @Override
    @Logs
    @Transactional
    public void updateArticle(Article article) {
        articleMapper.updateArticle(article);
    }

    @Override
    @Logs
    @Transactional
    public void deleteArticle(Long id) {
        Article article = articleMapper.getArticleById(id);
        String articlePic = article.getArticlePic();
        String[] arr = articlePic.split("/");
        String fileName = arr[arr.length - 1];
        minIoController.delete(fileName);
        articleMapper.deleteArticle(id);
    }

    @Override
    public Article getArticleById(Long id) {
        return articleMapper.getArticleById(id);
    }

    @Override
    public List<Article> getArticleAll() {
        return articleMapper.getArticleAll();
    }

    @Override
    public PageInfo<Article> getArticleByPage(ArticleQuery articleQuery) {
        PageHelper.startPage(articleQuery.getPage(), articleQuery.getSize());
        List<Article> page = articleMapper.getArticleByPage(articleQuery);
        PageInfo<Article> pageInfo = new PageInfo<>(page);
        return pageInfo;
    }

    @Override
    @Logs
    @Transactional
    public void batchdelArticle(List<Long> ids) {
        List<Article> articleAll = articleMapper.getArticleAll();
        List<String> articlePics = articleAll
                .stream()
                .map(Article::getArticlePic)
                .collect(Collectors.toList());
        articlePics.forEach(articlePic -> {
            String[] arr = articlePic.split("/");
            String fileName = arr[arr.length - 1];
            minIoController.delete(fileName);
        });
        articleMapper.batchdelArticle(ids);
    }

    @Override
    public PageInfo<Article> getPage(ArticleQuery articleQuery) {
        PageHelper.startPage(articleQuery.getPage(), articleQuery.getSize());
        List<Article> page = articleMapper.getPage(articleQuery);
        PageInfo<Article> pageInfo = new PageInfo<>(page);
        return pageInfo;
    }

    @Override
    @Logs
    @Transactional
    public Integer star(HttpServletRequest request,Long id) {
        Article articleById = articleMapper.getArticleById(id);
        String ip = request.getRemoteAddr();
        if(!redisTemplate.hasKey(ARTICLE_STAR+ip)){
            redisTemplate.opsForValue().set(ARTICLE_STAR+ip,1,24, TimeUnit.HOURS);
            articleById.setArticleStarNum(articleById.getArticleStarNum()+1);
            articleMapper.updateArticle(articleById);
            return articleById.getArticleStarNum();
        }
        return articleById.getArticleStarNum();
    }

    @Override
    @Logs
    @Transactional
    public Integer read(HttpServletRequest request, Long id) {
        Article articleById = articleMapper.getArticleById(id);
        String ip = request.getRemoteAddr();
        if(!redisTemplate.hasKey(ARTICLE_READ+ip)){
            redisTemplate.opsForValue().set(ARTICLE_READ+ip,1,24, TimeUnit.HOURS);
            articleById.setArticleReadCount(articleById.getArticleReadCount()+1);
            articleMapper.updateArticle(articleById);
            return articleById.getArticleReadCount();
        }
        return articleById.getArticleReadCount();
    }

    @Override
    public List<TypeNameCount> findByTypeName() {
        return articleMapper.findByTypeName();
    }

    @Override
    public Map<Integer, List<Article>> getArticleYear() {
        List<Article> articleAll = articleMapper.getArticleAll();
        Map<Integer,List<Article>> listMap = articleAll.stream()
                .filter(article -> article.getArticleState() == 1)
                .filter(article -> article.getUpdateTime() != null)
                .collect(Collectors.groupingBy(article -> {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(article.getUpdateTime());
                    return calendar.get(Calendar.YEAR);
                })
                );
        return listMap;
    }

    @Override
    public List<YearAndMonth> findByYearAndMonth() {
        return articleMapper.findByYearAndMonth();
    }

    @Override
    public List<Bar> fingStarsAndNameByArticle() {
        return articleMapper.fingStarsAndNameByArticle();
    }
}
